package com.sky.skyopsserver.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sky.skyopsserver.domain.Host;
import com.sky.skyopsserver.domain.HostGroup;
import com.sky.skyopsserver.enums.ResponseCodeEnum;
import com.sky.skyopsserver.exception.BizException;
import com.sky.skyopsserver.mapper.HostGroupMapper;
import com.sky.skyopsserver.mapper.HostMapper;
import com.sky.skyopsserver.service.HostGroupService;
import com.sky.skyopsserver.vos.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.time.YearMonth;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 主机组信息服务实现类
 * 
 * @author Administrator
 * @description 针对表【host_group(主机组信息表)】的数据库操作Service实现
 * @createDate 2025-09-13 17:43:03
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class HostGroupServiceImpl extends ServiceImpl<HostGroupMapper, HostGroup>
        implements HostGroupService {

    private final HostMapper hostMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long addHostGroup(HostGroupAddReqVO reqVO) {
        log.info("开始添加主机组，组名称: {}", reqVO.getName());
        
        // 检查主机组名称是否已存在
        if (checkHostGroupNameExists(reqVO.getName(), null)) {
            throw new BizException(ResponseCodeEnum.HOST_GROUP_NAME_EXISTS);
        }
        
        // 构建主机组实体
        HostGroup hostGroup = HostGroup.builder()
                .name(reqVO.getName())
                .remark(reqVO.getRemark())
                .createTime(LocalDateTime.now())
                .build();
        
        // 保存到数据库
        boolean saved = save(hostGroup);
        if (!saved) {
            throw new BizException(ResponseCodeEnum.HOST_GROUP_ADD_FAILED);
        }
        
        log.info("主机组添加成功，主机组ID: {}", hostGroup.getId());
        return hostGroup.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateHostGroup(HostGroupUpdateReqVO reqVO) {
        log.info("开始更新主机组，主机组ID: {}", reqVO.getId());
        
        // 检查主机组是否存在
        HostGroup existingGroup = getById(reqVO.getId());
        if (Objects.isNull(existingGroup)) {
            throw new BizException(ResponseCodeEnum.HOST_GROUP_NOT_EXISTS);
        }
        
        // 检查主机组名称是否已被其他主机组使用
        if (checkHostGroupNameExists(reqVO.getName(), reqVO.getId())) {
            throw new BizException(ResponseCodeEnum.HOST_GROUP_NAME_EXISTS);
        }
        
        // 更新主机组信息
        HostGroup hostGroup = new HostGroup();
        BeanUtils.copyProperties(reqVO, hostGroup);
        
        boolean updated = updateById(hostGroup);
        if (!updated) {
            throw new BizException(ResponseCodeEnum.HOST_GROUP_UPDATE_FAILED);
        }
        
        log.info("主机组更新成功，主机组ID: {}", reqVO.getId());
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteHostGroup(Long id) {
        log.info("开始删除主机组，主机组ID: {}", id);
        
        // 检查主机组是否存在
        HostGroup existingGroup = getById(id);
        if (Objects.isNull(existingGroup)) {
            throw new BizException(ResponseCodeEnum.HOST_GROUP_NOT_EXISTS);
        }
        
        // 检查主机组下是否有主机
        Long hostCount = getHostCountByGroupId(id);
        if (hostCount > 0) {
            throw new BizException(ResponseCodeEnum.HOST_GROUP_HAS_HOSTS);
        }
        
        boolean deleted = removeById(id);
        if (!deleted) {
            throw new BizException(ResponseCodeEnum.HOST_GROUP_DELETE_FAILED);
        }
        
        log.info("主机组删除成功，主机组ID: {}", id);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchDeleteHostGroup(List<Long> ids) {
        log.info("开始批量删除主机组，主机组ID列表: {}", ids);
        
        if (CollectionUtils.isEmpty(ids)) {
            throw new BizException(ResponseCodeEnum.PARAM_NOT_VALID);
        }
        
        // 检查所有主机组是否存在
        List<HostGroup> existingGroups = listByIds(ids);
        if (existingGroups.size() != ids.size()) {
            throw new BizException(ResponseCodeEnum.HOST_GROUP_NOT_EXISTS);
        }
        
        // 检查主机组下是否有主机
        Map<Long, Long> hostCountMap = getHostCountByGroupIds(ids);
        List<Long> groupsWithHosts = hostCountMap.entrySet().stream()
                .filter(entry -> entry.getValue() > 0)
                .map(Map.Entry::getKey)
                .toList();
        
        if (!groupsWithHosts.isEmpty()) {
            throw new BizException(ResponseCodeEnum.HOST_GROUP_HAS_HOSTS);

        }
        
        boolean deleted = removeByIds(ids);
        if (!deleted) {
            throw new BizException(ResponseCodeEnum.HOST_GROUP_DELETE_FAILED);

        }
        
        log.info("主机组批量删除成功，删除数量: {}", ids.size());
        return true;
    }

    @Override
    public HostGroupRspVO getHostGroupById(Long id) {
        log.info("查询主机组详情，主机组ID: {}", id);
        
        HostGroup hostGroup = getById(id);
        if (Objects.isNull(hostGroup)) {
            throw new BizException(ResponseCodeEnum.HOST_GROUP_NOT_EXISTS);
        }
        
        HostGroupRspVO rspVO = new HostGroupRspVO();
        BeanUtils.copyProperties(hostGroup, rspVO);
        
        // 设置主机数量
        Long hostCount = getHostCountByGroupId(id);
        rspVO.setHostCount(hostCount);
        
        return rspVO;
    }

    @Override
    public HostGroupDetailRspVO getHostGroupDetailById(Long id) {
        log.info("查询主机组详情（包含主机列表），主机组ID: {}", id);
        
        HostGroup hostGroup = getById(id);
        if (Objects.isNull(hostGroup)) {
            throw new BizException(ResponseCodeEnum.HOST_GROUP_NOT_EXISTS);

        }
        
        HostGroupDetailRspVO rspVO = new HostGroupDetailRspVO();
        BeanUtils.copyProperties(hostGroup, rspVO);
        
        // 查询主机列表
        List<Host> hosts = hostMapper.selectList(new LambdaQueryWrapper<Host>()
                .eq(Host::getGroupId, id)
                .orderByAsc(Host::getName));
        
        List<HostGroupDetailRspVO.HostSimpleInfo> hostInfos = hosts.stream()
                .map(host -> HostGroupDetailRspVO.HostSimpleInfo.builder()
                        .id(host.getId())
                        .name(host.getName())
                        .publicHost(host.getPublicHost())
                        .privateHost(host.getPrivateHost())
                        .type(host.getType())
                        .osVersion(host.getOsVersion())
                        .build())
                .collect(Collectors.toList());
        
        rspVO.setHosts(hostInfos);
        rspVO.setHostCount((long) hostInfos.size());
        
        return rspVO;
    }

    @Override
    public IPage<HostGroupRspVO> getHostGroupPage(HostGroupPageReqVO reqVO) {
        log.info("分页查询主机组列表，查询条件: {}", reqVO);
        
        // 构建分页对象
        Page<HostGroup> page = new Page<>(reqVO.getCurrent(), reqVO.getSize());
        
        // 构建查询条件
        LambdaQueryWrapper<HostGroup> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.hasText(reqVO.getName()), HostGroup::getName, reqVO.getName())
                   .like(StringUtils.hasText(reqVO.getRemark()), HostGroup::getRemark, reqVO.getRemark())
                   .orderByDesc(HostGroup::getCreateTime);
        
        // 执行分页查询
        IPage<HostGroup> hostGroupPage = page(page, queryWrapper);
        
        // 获取所有主机组的主机数量
        List<Long> groupIds = hostGroupPage.getRecords().stream()
                .map(HostGroup::getId)
                .collect(Collectors.toList());
        Map<Long, Long> hostCountMap = getHostCountByGroupIds(groupIds);
        
        // 转换为响应VO
        IPage<HostGroupRspVO> rspPage = hostGroupPage.convert(hostGroup -> {
            HostGroupRspVO rspVO = new HostGroupRspVO();
            BeanUtils.copyProperties(hostGroup, rspVO);
            rspVO.setHostCount(hostCountMap.getOrDefault(hostGroup.getId(), 0L));
            return rspVO;
        });
        
        log.info("分页查询主机组列表完成，总记录数: {}", rspPage.getTotal());
        return rspPage;
    }

    @Override
    public List<HostGroupOptionRspVO> getAllHostGroupOptions() {
        log.info("查询所有主机组选项");
        
        List<HostGroup> hostGroups = list(new LambdaQueryWrapper<HostGroup>()
                .orderByAsc(HostGroup::getName));
        
        // 获取所有主机组的主机数量
        List<Long> groupIds = hostGroups.stream()
                .map(HostGroup::getId)
                .collect(Collectors.toList());
        Map<Long, Long> hostCountMap = getHostCountByGroupIds(groupIds);
        
        return hostGroups.stream()
                .map(hostGroup -> convertToOptionVO(hostGroup, hostCountMap.getOrDefault(hostGroup.getId(), 0L)))
                .collect(Collectors.toList());
    }

    @Override
    public List<HostGroupOptionRspVO> getHostGroupOptionsWithHosts() {
        log.info("查询有主机的主机组选项");
        
        // 先获取有主机的主机组ID
        List<Long> groupIdsWithHosts = hostMapper.selectList(new LambdaQueryWrapper<Host>()
                        .select(Host::getGroupId)
                        .groupBy(Host::getGroupId))
                .stream()
                .map(Host::getGroupId)
                .collect(Collectors.toList());
        
        if (CollectionUtils.isEmpty(groupIdsWithHosts)) {
            return new ArrayList<>();
        }
        
        List<HostGroup> hostGroups = listByIds(groupIdsWithHosts);
        Map<Long, Long> hostCountMap = getHostCountByGroupIds(groupIdsWithHosts);
        
        return hostGroups.stream()
                .map(hostGroup -> convertToOptionVO(hostGroup, hostCountMap.getOrDefault(hostGroup.getId(), 0L)))
                .sorted(Comparator.comparing(HostGroupOptionRspVO::getName))
                .collect(Collectors.toList());
    }

    @Override
    public List<HostGroupOptionRspVO> getEmptyHostGroupOptions() {
        log.info("查询空主机组选项");
        
        // 获取所有主机组
        List<HostGroup> allGroups = list();
        
        // 获取有主机的主机组ID
        Set<Long> groupIdsWithHosts = hostMapper.selectList(new LambdaQueryWrapper<Host>()
                        .select(Host::getGroupId)
                        .groupBy(Host::getGroupId))
                .stream()
                .map(Host::getGroupId)
                .collect(Collectors.toSet());
        
        // 过滤出空主机组
        return allGroups.stream()
                .filter(group -> !groupIdsWithHosts.contains(group.getId()))
                .map(hostGroup -> convertToOptionVO(hostGroup, 0L))
                .sorted(Comparator.comparing(HostGroupOptionRspVO::getName))
                .collect(Collectors.toList());
    }

    @Override
    public HostGroupStatisticsRspVO getHostGroupStatistics() {
        log.info("获取主机组统计信息");
        
        // 主机组总数
        long totalCount = count();
        
        // 主机总数
        long totalHostCount = hostMapper.selectCount(new LambdaQueryWrapper<>());
        
        // 有主机的组数量
        long groupsWithHostsCount = hostMapper.selectList(new LambdaQueryWrapper<Host>()
                        .select(Host::getGroupId)
                        .groupBy(Host::getGroupId))
                .size();
        
        // 空组数量
        long emptyGroupsCount = totalCount - groupsWithHostsCount;
        
        // 本月新增主机组数量
        YearMonth currentMonth = YearMonth.now();
        LocalDateTime monthStart = currentMonth.atDay(1).atStartOfDay();
        LocalDateTime monthEnd = currentMonth.atEndOfMonth().atTime(23, 59, 59);
        
        long monthlyAddedCount = count(new LambdaQueryWrapper<HostGroup>()
                .between(HostGroup::getCreateTime, monthStart, monthEnd));
        
        // 平均每组主机数
        double avgHostsPerGroup = totalCount > 0 ? (double) totalHostCount / totalCount : 0.0;
        
        return HostGroupStatisticsRspVO.builder()
                .totalCount(totalCount)
                .groupsWithHostsCount(groupsWithHostsCount)
                .emptyGroupsCount(emptyGroupsCount)
                .monthlyAddedCount(monthlyAddedCount)
                .totalHostCount(totalHostCount)
                .avgHostsPerGroup(Math.round(avgHostsPerGroup * 100.0) / 100.0)
                .build();
    }

    @Override
    public Boolean checkHostGroupNameExists(String name, Long excludeId) {
        LambdaQueryWrapper<HostGroup> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(HostGroup::getName, name);
        
        if (Objects.nonNull(excludeId)) {
            queryWrapper.ne(HostGroup::getId, excludeId);
        }
        
        return count(queryWrapper) > 0;
    }

    @Override
    public List<HostGroupRspVO> searchHostGroupByName(String name) {
        log.info("根据名称模糊查询主机组，关键字: {}", name);
        
        List<HostGroup> hostGroups = list(new LambdaQueryWrapper<HostGroup>()
                .like(StringUtils.hasText(name), HostGroup::getName, name)
                .orderByAsc(HostGroup::getName));
        
        // 获取主机数量
        List<Long> groupIds = hostGroups.stream()
                .map(HostGroup::getId)
                .collect(Collectors.toList());
        Map<Long, Long> hostCountMap = getHostCountByGroupIds(groupIds);
        
        return hostGroups.stream()
                .map(hostGroup -> {
                    HostGroupRspVO rspVO = new HostGroupRspVO();
                    BeanUtils.copyProperties(hostGroup, rspVO);
                    rspVO.setHostCount(hostCountMap.getOrDefault(hostGroup.getId(), 0L));
                    return rspVO;
                })
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean moveHostsToGroup(List<Long> hostIds, Long targetGroupId) {
        log.info("移动主机到指定主机组，主机ID列表: {}, 目标主机组ID: {}", hostIds, targetGroupId);
        
        if (CollectionUtils.isEmpty(hostIds)) {
            throw new BizException(ResponseCodeEnum.PARAM_NOT_VALID);

        }
        
        // 检查目标主机组是否存在
        HostGroup targetGroup = getById(targetGroupId);
        if (Objects.isNull(targetGroup)) {
            throw new BizException(ResponseCodeEnum.HOST_GROUP_NOT_EXISTS);

        }
        
        // 检查主机是否存在
        List<Host> hosts = hostMapper.selectByIds(hostIds);
        if (hosts.size() != hostIds.size()) {
            throw new BizException(ResponseCodeEnum.HOST_NOT_EXISTS);

        }
        
        // 更新主机的主机组信息
        hosts.forEach(host -> {
            host.setGroupId(targetGroupId);
            host.setGroupName(targetGroup.getName());
        });
        
        // 批量更新
        hosts.forEach(hostMapper::updateById);
        
        log.info("主机移动成功，移动数量: {}", hostIds.size());
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean removeHostsFromGroup(List<Long> hostIds, Long groupId) {
        log.info("从主机组中移除主机，主机ID列表: {}, 主机组ID: {}", hostIds, groupId);

        if (CollectionUtils.isEmpty(hostIds)) {
            throw new BizException(ResponseCodeEnum.PARAM_NOT_VALID);

        }
        
        // 检查主机是否属于指定主机组
        List<Host> hosts = hostMapper.selectList(new LambdaQueryWrapper<Host>()
                .in(Host::getId, hostIds)
                .eq(Host::getGroupId, groupId));
        
        if (hosts.size() != hostIds.size()) {
            throw new BizException(ResponseCodeEnum.HOST_NOT_IN_GROUP);

        }
        
        // 这里可以设置为默认主机组或者设置为null，根据业务需求决定
        // 暂时设置为null
        hosts.forEach(host -> {
            host.setGroupId(null);
            host.setGroupName(null);
        });
        
        // 批量更新
        hosts.forEach(hostMapper::updateById);
        
        log.info("主机移除成功，移除数量: {}", hostIds.size());
        return true;
    }

    @Override
    public Long getHostCountByGroupId(Long groupId) {
        return hostMapper.selectCount(new LambdaQueryWrapper<Host>()
                .eq(Host::getGroupId, groupId));
    }

    @Override
    public Map<Long, Long> getHostCountByGroupIds(List<Long> groupIds) {
        if (CollectionUtils.isEmpty(groupIds)) {
            return new HashMap<>();
        }
        
        // 查询每个主机组的主机数量
        List<Host> hosts = hostMapper.selectList(new LambdaQueryWrapper<Host>()
                .select(Host::getGroupId)
                .in(Host::getGroupId, groupIds));
        
        // 统计每个主机组的主机数量
        Map<Long, Long> hostCountMap = hosts.stream()
                .collect(Collectors.groupingBy(Host::getGroupId, Collectors.counting()));
        
        // 确保所有主机组都有记录，没有主机的主机组设置为0
        groupIds.forEach(groupId -> hostCountMap.putIfAbsent(groupId, 0L));
        
        return hostCountMap;
    }

    /**
     * 转换为选项VO
     * 
     * @param hostGroup 主机组实体
     * @param hostCount 主机数量
     * @return 选项VO
     */
    private HostGroupOptionRspVO convertToOptionVO(HostGroup hostGroup, Long hostCount) {
        return HostGroupOptionRspVO.builder()
                .id(hostGroup.getId())
                .name(hostGroup.getName())
                .hostCount(hostCount)
                .remark(hostGroup.getRemark())
                .build();
    }
}




